package com.example.demo_mysql_mybatisplus.configs;


import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;

/**
 * mybatisPlus之自动填充工具MetaObjectHandler使用demo及注意点
 *      https://blog.csdn.net/csdn_20150804/article/details/121584855
 *
 * 按照上文步骤配置了后，在新增和更新实体对象时，就会自动赋值了，但是，并不是所有场景都会自动填充的，有一些失效场景需要注意：
 *
 * 1. 使用mapper.xml的sql不生效
 *      必须使用mybatis的api进行插入和更新操作才生效。
 *
 * 2. boolean update(Wrapper updateWrapper) 不生效
 * 不生效方式：
 *  this.update( new UpdateWrapper<User>().set("name", "张三")));
 * 生效方式：
 *  this.update(new User(), new UpdateWrapper<User>() .set("name", "张三")) );
 *
 * 3. @TableField注解要加上
 * @TableField(value = “update_time”, fill = FieldFill.UPDATE)
 * 实现接口后，此注解也要加，并且指定fill参数值，不然不会填充。
 *
 * 4. 其他
 * 如果属性有值则不覆盖,如果sql中赋值了，自动填充又设置为其他值，则已sql中的值为准‘
 * 如果填充值为null则不填充；比如this.setFieldValByName(“update_time”, null, metaObject); 实际是不会更新为null的；
 *
 * 总结：
 *      xxxFill方式只适用于使用mybatiesPlus提供的方法进行update/insert操作；
 *      @insert、@update 方式不在其增强范围，fill字段需要自己手动填充
 *      Mapper.xml 也不在其增强范围，fill字段需要自己手动填充
 * */
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    private final static String CREATE_TIME = "createTime";
    private final static String CREATE_BY = "createBy";
    private final static String UPDATE_TIME = "updateTime";
    private final static String UPDATE_BY = "updateBy";

    @Override
    public void insertFill(MetaObject metaObject) {
        if( this.getFieldValByName(CREATE_TIME,metaObject) == null){
            setFieldValue( CREATE_TIME ,  getDate(),  metaObject);
        }
        if( this.getFieldValByName(CREATE_BY,metaObject) == null){
            setFieldValue( CREATE_BY,  10000L,  metaObject);
        }
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        if( this.getFieldValByName(UPDATE_TIME,metaObject) == null){
            setFieldValue( UPDATE_TIME ,  getDate(),  metaObject);
        }
        if( this.getFieldValByName(UPDATE_BY,metaObject) == null){
            setFieldValue( UPDATE_BY ,  10000L,  metaObject);
        }
    }

    private void setFieldValue(String field , Object value , MetaObject metaObject) {
        if(metaObject.hasGetter(field)){
            this.setFieldValByName(field, value ,metaObject);// 不会报错，但加个判断好点
        }else{
            System.out.println("Class ["+metaObject.getOriginalObject().getClass().getSimpleName()+"] doesn't have get method for field: "+field);
        }
    }

    private Date getDate(){
        return Calendar.getInstance().getTime() ;
    }

    private Long getUserId(){
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if(null!=attributes){
            HttpServletRequest request = Objects.requireNonNull(attributes).getRequest();
            String userId = request.getHeader("Authorization");
            return userId==null?null:Long.valueOf(userId);
        }
        return null;
    }

}
